package org.brakepedal.server.support.controller.responseBodyAdvice;

import lombok.extern.slf4j.Slf4j;
import org.brakepedal.server.support.http.AbsResponseBody;
import org.brakepedal.server.support.http.ComResponseBody;
import org.jetbrains.annotations.NotNull;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * 统一响应体处理器
 * 可以优化的点: 包装返回结果的对象每次都是通过 new 创建的,
 * 其实只要重置一遍,就可以在不同请求间复用, 省却创建时间, 没有对象的更换
 * 也会节省垃圾回收所耗费的时间
 *
 * 不对,如果使用 reset() 后再设置值的方式来包装的话,有可能遇到并发
 */
@Slf4j
@RestControllerAdvice/*(annotations = ComBody.class, basePackages = "com.pdl.chatroomjava.controller")*/
@Order(8000)
public class WrapIntoComResponseBodyAdvice implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(@NotNull MethodParameter returnType, @NotNull Class converterType) {
        // 从ioc容器中取出 PageResponseBodyAdvice 实例, 若PageResponseBodyAdvice 可以处理则 ComResponseBodyAdvice 不处理
        return AdviceSupportUtil.isPlainBody(returnType,converterType);
    }

    @Override
    public Object beforeBodyWrite(Object body, @NotNull MethodParameter returnType,
                                  @NotNull MediaType selectedContentType, @NotNull Class selectedConverterType,
                                  @NotNull ServerHttpRequest request, @NotNull ServerHttpResponse response) {

        if(body == null || ComResponseBody.SUCCESS.getMsg().equals(body)) {
            return ComResponseBody.SUCCESS;
        } else if(ComResponseBody.WARN.getMsg().equals(body)) {
            return ComResponseBody.WARN;
        } else if (ComResponseBody.ERROR.getMsg().equals(body)) {
            return ComResponseBody.ERROR;
        }

        // 判断响应的Content-Type为JSON格式的body
        if(body instanceof AbsResponseBody){ // 如果响应返回的对象为统一响应体，则直接返回bodyd
            return body;
        }
        ComResponseBody res = ComResponseBody.ok(body);
        // 只有正常返回的结果才会进入这个判断流程，所以返回正常成功的状态码
        return res;
    }
}

